///////////////////////////////////////////////////////////////////////////////
//$Date: 2008/05/30 00:57:53 $
//$RCSfile: frame_check.ejava,v $
//$Revision: 1.1.2.1 $
///////////////////////////////////////////////////////////////////////////////
//   ____  ____ 
//  /   /\/   / 
// /___/  \  /    Vendor: Xilinx 
// \   \   \/     Version : 1.5
//  \   \         Application : RocketIO GTX Wizard 
//  /   /         Filename : frame_check.v
// /___/   /\     Timestamp : 
// \   \  /  \ 
//  \___\/\___\ 
//
//
// Module FRAME_CHECK
// Generated by Xilinx RocketIO GTX Wizard

`timescale 1ns / 1ps
`define DLY #1

//***********************************Entity Declaration************************

module FRAME_CHECK #
(
    // parameter to set the number of words in the BRAM
    parameter   RX_DATA_WIDTH            =   16,
    parameter   NONE_MSB_FIRST_DEC       =   0,
    parameter   COMMA_DOUBLE_DEC         =   0,
    parameter   CHANBOND_SEQ_LEN         =   1,
    parameter   USE_COMMA                =   1,
    parameter   WORDS_IN_BRAM            =   256,
    parameter   CONFIG_INDEPENDENT_LANES =   0,
    parameter   START_OF_PACKET_CHAR     =  16'h55fb,
    parameter   COMMA_DOUBLE             =  16'hf628,
    parameter   MEM_00   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_01   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_02   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_03   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_04   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_05   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_06   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_07   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_08   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_09   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_0A   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_0B   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_0C   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_0D   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_0E   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_0F   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_10   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_11   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_12   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_13   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_14   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_15   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_16   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_17   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_18   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_19   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_1A   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_1B   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_1C   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_1D   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_1E   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_1F   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_20   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_21   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_22   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_23   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_24   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_25   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_26   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_27   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_28   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_29   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_2A   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_2B   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_2C   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_2D   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_2E   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_2F   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_30   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_31   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_32   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_33   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_34   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_35   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_36   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_37   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_38   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_39   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_3A   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_3B   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_3C   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_3D   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_3E   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEM_3F   =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_00  =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_01  =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_02  =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_03  =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_04  =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_05  =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_06  =   256'h0000000000000000000000000000000000000000000000000000000000000000,
    parameter   MEMP_07  =   256'h0000000000000000000000000000000000000000000000000000000000000000
)                            
(
    // User Interface
    RX_DATA,  
    RX_ENMCOMMA_ALIGN,
    RX_ENPCOMMA_ALIGN,
    RX_ENCHAN_SYNC,
    RX_CHANBOND_SEQ,

    // Control Interface
    INC_IN,
    INC_OUT,
    PATTERN_MATCH_N,
    RESET_ON_ERROR,
    
    // Error Monitoring
    ERROR_COUNT,

    // System Interface
    USER_CLK,       
    SYSTEM_RESET
);

// synthesis attribute X_CORE_INFO of FRAME_CHECK is "gtxwizard_v1_5, Coregen v10.1_ip3";

//***********************************Port Declarations*************************

    // User Interface
    input   [(RX_DATA_WIDTH-1):0] RX_DATA;
    output          RX_ENMCOMMA_ALIGN;
    output          RX_ENPCOMMA_ALIGN;
    output          RX_ENCHAN_SYNC;
    input           RX_CHANBOND_SEQ;

    // Control Interface
    input           INC_IN;
    output          INC_OUT;
    output          PATTERN_MATCH_N;
    input           RESET_ON_ERROR; 
    
    // Error Monitoring
    output  [7:0]   ERROR_COUNT;

    // System Interface
    input           USER_CLK;
    input           SYSTEM_RESET; 


//***************************Internal Register Declarations******************** 

    reg             begin_r;
    reg             data_error_detected_r;
    reg     [8:0]   error_count_r;
    reg             error_detected_r;
    reg     [8:0]   read_counter_i;    
    reg             rx_chanbond_seq_r;
    reg             rx_chanbond_seq_r2;
    reg             rx_chanbond_seq_r3;
    reg             RX_ENCHAN_SYNC;    
    reg             RX_ENMCOMMA_ALIGN;    
    reg             RX_ENPCOMMA_ALIGN;    
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r2;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r3;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r4;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r5;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r6;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r_track;
    reg             start_of_packet_detected_r;    
    reg             track_data_r;
    reg             track_data_r2;
    reg             track_data_r3;
    reg     [1:0]   sel;
    
 
//*********************************Wire Declarations***************************

    wire    [31:0]  bram_data_r;
    wire            error_detected_c;
    wire            input_to_chanbond_data_i;
    wire            input_to_chanbond_reg_i;
    wire            next_begin_c;
    wire            next_data_error_detected_c;
    wire            next_track_data_c;
    wire            start_of_packet_detected_c;
    wire    [(CHANBOND_SEQ_LEN-1):0]  rx_chanbond_reg;
    wire    [(RX_DATA_WIDTH-1):0]  rx_data_aligned;
    wire            rx_data_has_start_char_c;
    wire            tied_to_ground_i;
    wire    [31:0]  tied_to_ground_vec_i;
    wire            tied_to_vcc_i;

//*********************************Main Body of Code***************************

    //_______________________  Static signal Assigments _______________________   

    assign tied_to_ground_i             = 1'b0;
    assign tied_to_ground_vec_i         = 16'h0000;
    assign tied_to_vcc_i                = 1'b1;


    //______________________ Register RXDATA once to ease timing ______________   

    always @(posedge USER_CLK)
        rx_data_r <= `DLY    RX_DATA;

    //________________________________ State machine __________________________    
    
    // State registers
    always @(posedge USER_CLK)
        if(RESET_ON_ERROR | SYSTEM_RESET)
            {begin_r,track_data_r,data_error_detected_r}  <=  `DLY    3'b100;
        else
        begin
            begin_r                <=  `DLY    next_begin_c;
            track_data_r           <=  `DLY    next_track_data_c;
            data_error_detected_r  <=  `DLY    next_data_error_detected_c;
        end

    // Next state logic
    assign  next_begin_c                =   (begin_r & !start_of_packet_detected_r)
                                            | data_error_detected_r ;

    assign  next_track_data_c           =   (begin_r & start_of_packet_detected_r)
                                            | (track_data_r && !error_detected_r);
                                      
    assign  next_data_error_detected_c  =   (track_data_r && error_detected_r);                               
        
    assign  start_of_packet_detected_c  =   (CONFIG_INDEPENDENT_LANES==0)?INC_IN : rx_data_has_start_char_c;

    always @(posedge USER_CLK) 
        start_of_packet_detected_r    <=   `DLY  start_of_packet_detected_c;  

    // Registering for timing
    always @(posedge USER_CLK) 
        track_data_r2    <=   `DLY  track_data_r;  

    always @(posedge USER_CLK) 
        track_data_r3    <=   `DLY  track_data_r2;  
    
    //______________________________ Capture incoming data ____________________    

generate
if (((RX_DATA_WIDTH==32) || (RX_DATA_WIDTH==40)) && (NONE_MSB_FIRST_DEC==1))
begin : datapath_width_32_or_40_none_msbfirst_decoding 
    always @(posedge USER_CLK)
    begin
        if(SYSTEM_RESET)    rx_data_r3 <= 'h0;
        else 
        begin
            if(sel == 2'b10)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r2[(RX_DATA_WIDTH/4-1):0],rx_data_r[(RX_DATA_WIDTH - 1):RX_DATA_WIDTH/4]};  
            end
            else if(sel == 2'b01)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r2[(RX_DATA_WIDTH/2-1):0],rx_data_r[(RX_DATA_WIDTH - 1):RX_DATA_WIDTH/2]};  
            end
            else if(sel == 2'b11)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r2[(3*RX_DATA_WIDTH/4 - 1):0],rx_data_r[(RX_DATA_WIDTH-1):3*RX_DATA_WIDTH/4]};  
            end
            else rx_data_r3  <=  `DLY    rx_data_r2;
        end
    end
end
else if (((RX_DATA_WIDTH==32) || (RX_DATA_WIDTH==40)) && (NONE_MSB_FIRST_DEC==0))
begin :datapath_width_32_or_40_not_none_msbfirst_decoding
    always @(posedge USER_CLK)
    begin
        if(SYSTEM_RESET)    rx_data_r3 <= 'h0;
        else
        begin
            if(sel == 2'b10)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(RX_DATA_WIDTH/4 - 1):0],rx_data_r2[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/4]};  
            end
            else if(sel == 2'b01)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(RX_DATA_WIDTH/2-1):0],rx_data_r2[(RX_DATA_WIDTH - 1):RX_DATA_WIDTH/2]};  
            end
            else if(sel == 2'b11)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(3*RX_DATA_WIDTH/4-1):0],rx_data_r2[(RX_DATA_WIDTH - 1):3*RX_DATA_WIDTH/4]};  
            end
            else rx_data_r3  <=  `DLY    rx_data_r2;
        end
    end
end
else if (((RX_DATA_WIDTH==16) || (RX_DATA_WIDTH==20)) && (NONE_MSB_FIRST_DEC==0))
begin :datapath_width_16_or_20_not_none_msbfirst_decoding
    always @(posedge USER_CLK)
    begin
        if(SYSTEM_RESET)    rx_data_r3 <= 'h0;
        else
        begin
            if(sel == 2'b01)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(RX_DATA_WIDTH/2 - 1):0],rx_data_r2[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2]};  
            end
	    else rx_data_r3  <=  `DLY    rx_data_r2;
        end
    end
end
else if (((RX_DATA_WIDTH==16) || (RX_DATA_WIDTH==20)) && (NONE_MSB_FIRST_DEC==1))
begin :datapath_width_16_or_20_none_msbfirst_decoding
    always @(posedge USER_CLK)
    begin
        if(SYSTEM_RESET)    rx_data_r3 <= 'h0;
        else
        begin
            if(sel == 2'b01)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r2[(RX_DATA_WIDTH/2 - 1):0],rx_data_r[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2]};  
            end
	    else rx_data_r3  <=  `DLY    rx_data_r2;
        end
    end
end
endgenerate

generate
if ((RX_DATA_WIDTH==32) || (RX_DATA_WIDTH==40) || (RX_DATA_WIDTH==16) || (RX_DATA_WIDTH==20))
begin : datapath_width_32_or_40_or_16_or_20 
    always @(posedge USER_CLK)
    begin
        if(SYSTEM_RESET)  
        begin
            rx_data_r2      <=  `DLY   'h0;
            rx_data_r4      <=  `DLY   'h0;
            rx_data_r5      <=  `DLY   'h0;
            rx_data_r6      <=  `DLY   'h0;
            rx_data_r_track <=  `DLY   'h0;
        end
        else
        begin
            rx_data_r2      <=  `DLY    rx_data_r;
            rx_data_r4      <=  `DLY    rx_data_r3;
            rx_data_r5      <=  `DLY    rx_data_r4;
            rx_data_r6      <=  `DLY    rx_data_r5;
            rx_data_r_track <=  `DLY    rx_data_r6;
        end
    end

    assign rx_data_aligned = rx_data_r3;

    //___________________________ Code for Channel bonding ____________________    
    // code to prevent checking of clock correction sequences for the start of packet char
    always @(posedge USER_CLK)
    begin
        rx_chanbond_seq_r  <=  `DLY    RX_CHANBOND_SEQ;
        rx_chanbond_seq_r2 <=  `DLY    rx_chanbond_seq_r;
        rx_chanbond_seq_r3 <=  `DLY    rx_chanbond_seq_r2;
    end
    
    assign input_to_chanbond_reg_i  = rx_chanbond_seq_r2;
    assign input_to_chanbond_data_i = tied_to_ground_i;

end
endgenerate

generate
if (((RX_DATA_WIDTH==32) || (RX_DATA_WIDTH==40)) && (COMMA_DOUBLE_DEC==0))
begin : datapath_width_32_or_40 // Comma realignment logic might be needed. 4 levels of registering for RXDATA to meet timing
    // In 4 Byte scenario, when align_comma_word=2, Comma can appear on any of the three lower bytes
    // { BYTE3 | BYTE2 | BYTE1 | BYTE0 } - Comma can appear on BYTE0/1/2
    // If Comma appears on BYTE1/2, RX_DATA is realigned so that Comma appears on BYTE0 in rx_data_r_track

    always @(posedge USER_CLK)
    begin
        if(RESET_ON_ERROR | SYSTEM_RESET)    sel <= 2'b00;
        else if (begin_r & !(rx_chanbond_seq_r | rx_chanbond_seq_r2))
        begin
             // if Comma appears on BYTE3 ..
            if(rx_data_r[(RX_DATA_WIDTH - 1) : 3*RX_DATA_WIDTH/4] == START_OF_PACKET_CHAR) sel <= 2'b11;        
            // if Comma appears on BYTE2 ..
            else if(rx_data_r[(3*RX_DATA_WIDTH/4 - 1):RX_DATA_WIDTH/2] == START_OF_PACKET_CHAR)
            begin
                sel <= 2'b01;
            end
            // if Comma appears on BYTE1 ..
            else if(rx_data_r[(RX_DATA_WIDTH/2 - 1):RX_DATA_WIDTH/4] == START_OF_PACKET_CHAR)
            begin
                sel <= 2'b10;
            end
            // if Comma appears on BYTE0 ..
            else if(rx_data_r[(RX_DATA_WIDTH/4 - 1):0] == START_OF_PACKET_CHAR)
            begin
                sel <= 2'b00;
            end
        end      
    end
end
else if (((RX_DATA_WIDTH==32) || (RX_DATA_WIDTH==40)) && (COMMA_DOUBLE_DEC==1))
begin :datapath_width_32_or_40_comma_double

    // In 2 Byte scenario, when align_comma_word=1, Comma can appear on any of the two bytes
    // The comma is moved to the lower byte so that error checking can start
    always @(posedge USER_CLK)
    begin
        if(RESET_ON_ERROR | SYSTEM_RESET)    sel <= 2'b00;
        else if (begin_r & !(rx_chanbond_seq_r | rx_chanbond_seq_r2))
	begin
	     // if Comma appears on BYTE2 ..
	    if(rx_data_r[(RX_DATA_WIDTH/2 - 1):0] == COMMA_DOUBLE)     sel <= 2'b00;		
	    else if(rx_data_r[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2] == COMMA_DOUBLE)
	    begin
	        sel <= 2'b01;
	    end
        end      
    end
end
else if ((RX_DATA_WIDTH==16) || (RX_DATA_WIDTH==20))
begin :datapath_width_16_or_20

    // In 2 Byte scenario, when align_comma_word=1, Comma can appear on any of the two bytes
    // The comma is moved to the lower byte so that error checking can start
    always @(posedge USER_CLK)
    begin
        if(RESET_ON_ERROR | SYSTEM_RESET)    sel <= 2'b00;
        else if (begin_r & !(rx_chanbond_seq_r | rx_chanbond_seq_r2 | rx_chanbond_seq_r3))
	begin
	     // if Comma appears on BYTE2 ..
	    if(rx_data_r[(RX_DATA_WIDTH/2 - 1):0] == START_OF_PACKET_CHAR)     sel <= 2'b00;		
	    else if(rx_data_r[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2] == START_OF_PACKET_CHAR)
	    begin
	        sel <= 2'b01;
	    end
        end      
    end
end
else
begin : datapath_width_8_or_10
    always @(posedge USER_CLK)
    begin
        if(SYSTEM_RESET)  
        begin
            rx_data_r2      <=  `DLY   'h0;
            rx_data_r3      <=  `DLY   'h0;
            rx_data_r4      <=  `DLY   'h0;
            rx_data_r_track <=  `DLY   'h0;
        end
        else
        begin
            rx_data_r2      <=  `DLY    rx_data_r;
            rx_data_r3      <=  `DLY    rx_data_r2;
            rx_data_r4      <=  `DLY    rx_data_r3;
            rx_data_r_track <=  `DLY    rx_data_r4;
        end
    end

    assign rx_data_aligned = RX_DATA;
    assign input_to_chanbond_reg_i  = RX_CHANBOND_SEQ;
    assign input_to_chanbond_data_i = RX_CHANBOND_SEQ;

end
endgenerate

    //___________________________ Code for Channel bonding ____________________    
    // code to prevent checking of clock correction sequences for the start of packet char
    genvar i; 
    generate
    for (i=0;i<CHANBOND_SEQ_LEN ;i=i+1)
    begin:register_chan_seq
    if(i==0)
        FD rx_chanbond_reg  ( .Q (rx_chanbond_reg[i]), .D (input_to_chanbond_reg_i), .C(USER_CLK));
    else
        FD rx_chanbond_reg  ( .Q (rx_chanbond_reg[i]), .D (rx_chanbond_reg[i-1]), .C(USER_CLK));
    end
    endgenerate
    
    assign chanbondseq_in_data = |rx_chanbond_reg | input_to_chanbond_data_i;
    
generate
if (((RX_DATA_WIDTH==32) || (RX_DATA_WIDTH==16)) && (COMMA_DOUBLE_DEC==1))
begin : comma_double_decoding_and_32_16
    assign rx_data_has_start_char_c = (rx_data_aligned[15:0] == COMMA_DOUBLE) & !chanbondseq_in_data;
end
else if ((((RX_DATA_WIDTH==32) || (RX_DATA_WIDTH==16)) && (COMMA_DOUBLE_DEC==0)) || (RX_DATA_WIDTH==8))
begin : not_comma_double_and_32_16_or_8
    assign rx_data_has_start_char_c = (rx_data_aligned[7:0] == START_OF_PACKET_CHAR) & !chanbondseq_in_data;
end
else if (((RX_DATA_WIDTH==40) || (RX_DATA_WIDTH==20)) && (COMMA_DOUBLE_DEC==1))
begin : comma_double_decoding_and_40_or_20
    assign rx_data_has_start_char_c = (rx_data_aligned[19:0] == COMMA_DOUBLE) & !chanbondseq_in_data;
end
else 
begin : not_comma_double_and_40_20_or_10
    assign rx_data_has_start_char_c = (rx_data_aligned[9:0] == START_OF_PACKET_CHAR) & !chanbondseq_in_data;
end
endgenerate

    //_____________________________ Assign output ports _______________________    

    assign INC_OUT =  start_of_packet_detected_c;   

    assign PATTERN_MATCH_N =  data_error_detected_r;   

    // Drive the enamcommaalign port of the mgt for alignment
    always @(posedge USER_CLK)
        if(SYSTEM_RESET)  RX_ENMCOMMA_ALIGN   <=  `DLY    1'b0;
        else              RX_ENMCOMMA_ALIGN   <=  `DLY    1'b1;

    // Drive the enapcommaalign port of the mgt for alignment
    always @(posedge USER_CLK)
        if(SYSTEM_RESET)  RX_ENPCOMMA_ALIGN   <=  `DLY    1'b0;
        else              RX_ENPCOMMA_ALIGN   <=  `DLY    1'b1;

    // Drive the enchansync port of the mgt for channel bonding
    always @(posedge USER_CLK)
        if(SYSTEM_RESET)  RX_ENCHAN_SYNC   <=  `DLY    1'b0;
        else              RX_ENCHAN_SYNC   <=  `DLY    1'b1;

    //___________________________ Check incoming data for errors ______________
         
    //An error is detected when data read for the BRAM does not match the incoming data
generate
if (RX_DATA_WIDTH==40) 
begin : use_40bit
    assign  error_detected_c    =  track_data_r3 && (rx_data_r_track != {tied_to_ground_vec_i[7:0],bram_data_r});   
end
else
begin : not_40bit
    assign  error_detected_c    =  track_data_r3 && (rx_data_r_track !=  bram_data_r[(RX_DATA_WIDTH-1):0]);   
end
endgenerate
    
generate
if (USE_COMMA==1) 
begin : use_comma
    //We register the error_detected signal for use with the error counter logic
    always @(posedge USER_CLK)
        if(!track_data_r)  
            error_detected_r    <=  `DLY    1'b0;
        else
            error_detected_r    <=  `DLY    error_detected_c;  

end
else 
begin: no_comma
    // Since the comma detect logic has not been enabled, the error counter has been disabled since
    // it doesnt make sense to be searching for an align character in the data. To enable the error 
    // count again, please see the code above 
    
    always @(posedge USER_CLK)
        error_detected_r    <=   1'b0;

end
endgenerate

    //We count the total number of errors we detect. By keeping a count we make it less likely that we will miss
    //errors we did not directly observe. 
    always @(posedge USER_CLK)
        if(SYSTEM_RESET)
            error_count_r       <=  `DLY    9'd0;
        else if(error_detected_r)
            error_count_r       <=  `DLY    error_count_r + 1;    
    
    //Here we connect the lower 8 bits of the count (the MSbit is used only to check when the counter reaches
    //max value) to the module output
    assign  ERROR_COUNT =   error_count_r[7:0];
    //____________________________ Counter to read from BRAM __________________________    

    always @(posedge USER_CLK)
        if(SYSTEM_RESET |  (read_counter_i == (WORDS_IN_BRAM-1)) | (start_of_packet_detected_r & !track_data_r))  
        begin
            read_counter_i   <=  `DLY    9'd0;
        end
        else read_counter_i  <=  `DLY    read_counter_i + 9'd1;

    //________________________________ BRAM Instantiation _____________________________    

    RAMB16_S36_S36 #
    (
        .INIT_00(MEM_00),
        .INIT_01(MEM_01),
        .INIT_02(MEM_02),
        .INIT_03(MEM_03),
        .INIT_04(MEM_04),
        .INIT_05(MEM_05),
        .INIT_06(MEM_06),
        .INIT_07(MEM_07),
        .INIT_08(MEM_08),
        .INIT_09(MEM_09),
        .INIT_0A(MEM_0A),
        .INIT_0B(MEM_0B),
        .INIT_0C(MEM_0C),
        .INIT_0D(MEM_0D),
        .INIT_0E(MEM_0E),
        .INIT_0F(MEM_0F),
        .INIT_10(MEM_10),
        .INIT_11(MEM_11),
        .INIT_12(MEM_12),
        .INIT_13(MEM_13),
        .INIT_14(MEM_14),
        .INIT_15(MEM_15),
        .INIT_16(MEM_16),
        .INIT_17(MEM_17),
        .INIT_18(MEM_18),
        .INIT_19(MEM_19),
        .INIT_1A(MEM_1A),
        .INIT_1B(MEM_1B),
        .INIT_1C(MEM_1C),
        .INIT_1D(MEM_1D),
        .INIT_1E(MEM_1E),
        .INIT_1F(MEM_1F),
        .INIT_20(MEM_20),
        .INIT_21(MEM_21),
        .INIT_22(MEM_22),
        .INIT_23(MEM_23),
        .INIT_24(MEM_24),
        .INIT_25(MEM_25),
        .INIT_26(MEM_26),
        .INIT_27(MEM_27),
        .INIT_28(MEM_28),
        .INIT_29(MEM_29),
        .INIT_2A(MEM_2A),
        .INIT_2B(MEM_2B),
        .INIT_2C(MEM_2C),
        .INIT_2D(MEM_2D),
        .INIT_2E(MEM_2E),
        .INIT_2F(MEM_2F),
        .INIT_30(MEM_30),
        .INIT_31(MEM_31),
        .INIT_32(MEM_32),
        .INIT_33(MEM_33),
        .INIT_34(MEM_34),
        .INIT_35(MEM_35),
        .INIT_36(MEM_36),
        .INIT_37(MEM_37),
        .INIT_38(MEM_38),
        .INIT_39(MEM_39),
        .INIT_3A(MEM_3A),
        .INIT_3B(MEM_3B),
        .INIT_3C(MEM_3C),
        .INIT_3D(MEM_3D),
        .INIT_3E(MEM_3E),
        .INIT_3F(MEM_3F),
        .INITP_00(MEMP_00),
        .INITP_01(MEMP_01),
        .INITP_02(MEMP_02),
        .INITP_03(MEMP_03),
        .INITP_04(MEMP_04),
        .INITP_05(MEMP_05),
        .INITP_06(MEMP_06),
        .INITP_07(MEMP_07)

    )
    dual_port_block_ram_i 
    (
        .ADDRA (read_counter_i),
        .DIA   (tied_to_ground_vec_i[31:0]),
        .DIPA  (tied_to_ground_vec_i[3:0]),
        .DOA   (bram_data_r),
        .DOPA  ( ), 
        .WEA   (tied_to_ground_i),
        .ENA   (tied_to_vcc_i),
        .SSRA  (tied_to_ground_i), 
        .CLKA  (USER_CLK),
        
        .ADDRB (tied_to_ground_vec_i[8:0]),
        .DIB   (tied_to_ground_vec_i[31:0]),
        .DIPB  (tied_to_ground_vec_i[3:0]),
        .DOB   ( ),  
        .DOPB  ( ), 
        .WEB   (tied_to_ground_i),
        .ENB   (tied_to_ground_i),
        .SSRB  (tied_to_ground_i),
        .CLKB  (tied_to_ground_i)       
    );
    
    
endmodule           

